#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <limits.h>

#include <iostream>
#include <string>

#include <ctime>
#include <cstdlib>
#include <math.h>

//Incluyo la clase Mersenne-Twister para la generación de números aleatorios
#include "mt.h"

using namespace std;
//using std::string;

int cantGenesEnCromosomaDevice = 9;

int dondeEsta(int* poblacionActual, int valor, int posicionNuevoCromosoma){

	for(int i=0; i<cantGenesEnCromosomaDevice; i++){
		if(poblacionActual[posicionNuevoCromosoma+i]==valor)
			return i;
	}
	return 0;
}

void cruzamientoCromosomaPMX(int* poblacionActual, int* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad){
	int posicionNuevoCromosoma1 = posicionCromosoma1;
	int posicionNuevoCromosoma2 = posicionCromosoma2;

	unsigned int prob;
	prob = 40;
	cout<<"a";
	if(prob < probabilidad ){
		cout<<"b";
		int r1,r2;
		r1 = 2;r2 = 5;
		for(int j=0; j<cantGenesEnCromosomaDevice; j++){
			cout<<"c";
			if((j>=r1) && (j <= r2)){
				nuevaPoblacion[posicionNuevoCromosoma1+j] = poblacionActual[posicionCromosoma1+j];
				nuevaPoblacion[posicionNuevoCromosoma2+j] = poblacionActual[posicionCromosoma2+j];
			}else{
				nuevaPoblacion[posicionNuevoCromosoma1+j] = -1;
				nuevaPoblacion[posicionNuevoCromosoma2+j] = -1;
			}
		}
		cout<<"\n\n";
		for(int i =0; i<16;i++){
		  	  cout<<nuevaPoblacion[i]<<" ";
		    }
		cout<<"\nchau\n\n";
		int valor, valorInicial;
		for(int k=r1; k<=r2; k++){
			cout<<"k"<<k<<"\n";
			valor = poblacionActual[posicionCromosoma2+k];
			valorInicial = valor;
			cout<<"valor "<<valor;
			int pos = dondeEsta(poblacionActual,valor,posicionCromosoma1);
			cout<<" pos "<<pos<<"\n";
			if ((pos<r1) || (pos > r2)) {
				pos = k;
				cout<<"k="<<k<<"\n";
				valor = poblacionActual[posicionCromosoma1+pos];
				pos = dondeEsta(poblacionActual,valor,posicionCromosoma2);
				cout<<"valor " << valor <<" pos "<<pos<<"\n";
				while ((pos>=r1) && (pos <= r2)) {
					cout<<"taaa"<<"\n";
					valor = poblacionActual[posicionCromosoma1+pos];
					pos = dondeEsta(poblacionActual,valor,posicionCromosoma2);
					cout<<"valor " << valor <<" pos "<<pos<<"\n";
				}

				nuevaPoblacion[posicionNuevoCromosoma1+pos] = valorInicial;
			}
		}
		for(int k=r1; k<r2; k++){

			valor = poblacionActual[posicionCromosoma1+k];
			valorInicial = valor;
			int pos = dondeEsta(poblacionActual,valor,posicionCromosoma2);
			if ((pos<=r1) || (pos >= r2)) {
				pos = k;
				valor = poblacionActual[posicionCromosoma2+pos];
				pos = dondeEsta(poblacionActual,valor,posicionCromosoma1);
				while ((pos>=r1) && (pos <= r2)) {
					valor = poblacionActual[posicionCromosoma2+pos];
					pos = dondeEsta(poblacionActual,valor,posicionCromosoma1);
				}

				nuevaPoblacion[posicionNuevoCromosoma2+pos] = valorInicial;
			}
		}
		for(int i=0; i<cantGenesEnCromosomaDevice; i++){
			if(nuevaPoblacion[posicionNuevoCromosoma1+i] == -1)
				nuevaPoblacion[posicionNuevoCromosoma1+i] = poblacionActual[posicionCromosoma2+i];
			if(nuevaPoblacion[posicionNuevoCromosoma2+i] == -1)
				nuevaPoblacion[posicionNuevoCromosoma2+i] = poblacionActual[posicionCromosoma1+i];
		}
	}
	cout<<"\n\n";
			for(int i =0; i<16;i++){
			  	  cout<<nuevaPoblacion[i]<<" ";
			    }
			cout<<"\nchau\n\n";

}


int posicionPrimerLibre(int* poblacionActual, int posicionNuevoCromosoma){
	for(int i=0; i<cantGenesEnCromosomaDevice; i++){
		if(poblacionActual[posicionNuevoCromosoma+i]==-1)
			return i;
	}
	return -1;
}


void cruzamientoCromosomaCX(int* poblacionActual, int* nuevaPoblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad){
	int posicionNuevoCromosoma1 = posicionCromosoma1;
	int posicionNuevoCromosoma2 = posicionCromosoma2;
	int pos, pos2;
	unsigned int prob;
	prob = 40;
	if (prob < probabilidad){
		for(int i=0; i<cantGenesEnCromosomaDevice; i++){
			nuevaPoblacion[posicionNuevoCromosoma1+i] = -1;
			nuevaPoblacion[posicionNuevoCromosoma2+i] = -1;
		}
		int cont = 0;
		pos = posicionPrimerLibre(nuevaPoblacion, posicionCromosoma1);
		while (pos != -1) {
			if (cont == 0) {
				while(nuevaPoblacion[posicionCromosoma1 + pos] == -1) {
					nuevaPoblacion[posicionCromosoma1 + pos] = poblacionActual[posicionCromosoma1 + pos];
					pos2 = dondeEsta(poblacionActual, poblacionActual[posicionCromosoma1 + pos], posicionCromosoma2);
					nuevaPoblacion[posicionCromosoma2 + pos2] = poblacionActual[posicionCromosoma1 + pos];
					pos = pos2;
				}
			}
			else {
				while(nuevaPoblacion[posicionCromosoma2 + pos] == -1) {
					nuevaPoblacion[posicionCromosoma2 + pos] = poblacionActual[posicionCromosoma1 + pos];
					pos2 = dondeEsta(poblacionActual, poblacionActual[posicionCromosoma1 + pos], posicionCromosoma2);
					nuevaPoblacion[posicionCromosoma1 + pos2] = poblacionActual[posicionCromosoma1 + pos];
					pos = pos2;
				}
			}
			cont = (cont +1) % 2;
			pos = posicionPrimerLibre(nuevaPoblacion, posicionCromosoma1);
		}
	}
	for(int i =0; i<18;i++){
	  cout<<nuevaPoblacion[i]<<" ";
	}
}

int estaPresente(int valor, int* nuevaPoblacion, unsigned int tope){
	for (int i = 0; i< tope; i++) {
		if (nuevaPoblacion[i] == valor)
			return 1;
	}
	return 0;
}

void mutacionPorMezcla(int* poblacion, int posicionCromosoma1, int posicionCromosoma2, int probabilidad/*, struct Random randomGPU*/){
	int posicionNuevoCromosoma1 = posicionCromosoma1;
	int posicionNuevoCromosoma2 = posicionCromosoma2;

	int cantMezclados = 4;
	int arregloPosiciones[4];
	int arregloValores[4];
	int arregloPosicionesMezcladas[4];
	unsigned int r;
	for (int i = 0; i<cantMezclados; i++){
		r = 2;//(getRandomInt(randomGPU, posicionCromosoma)% cantGenesEnCromosomaDevice);
		while(estaPresente(r, arregloPosiciones, i)){
			r = (r+1) % cantGenesEnCromosomaDevice;
		}
		arregloPosiciones[i] = r;
	}

	for (int i = 0; i<cantMezclados; i++){
		r = 3;//(getRandomInt(randomGPU, posicionCromosoma)% cantGenesEnCromosomaDevice);
		while(estaPresente(arregloPosiciones[r], arregloPosicionesMezcladas, i)){
			r = (r+1) % cantMezclados;
		}
		arregloPosicionesMezcladas[i] = arregloPosiciones[r];
		arregloValores[i] = poblacion[posicionNuevoCromosoma1+arregloPosiciones[r]];
	}

	for (int i = 0; i<cantMezclados; i++){
		poblacion[posicionNuevoCromosoma1 + arregloPosiciones[i]] = arregloValores[i];
	}

/*	cout<<"\nPosiciones\n";
	for (int i =0; i<4;i++) {
	  cout<<arregloPosiciones[i]<<" ";
	}

	cout<<"\nPosiciones Mezcladas\n";
	for (int i =0; i<4;i++) {
	  cout<<arregloPosicionesMezcladas[i]<<" ";
	}
	cout<<"\nValores\n";
	for (int i =0; i<4;i++) {
	  cout<<arregloValores[i]<<" ";
	}
	cout<<"\n";*/
}

int main(){
  int tamVectorPoblacion = sizeof(int)*cantGenesEnCromosomaDevice*2;
  static int *poblacionActual = (int *) malloc(tamVectorPoblacion);
  static int *nuevaPoblacion = (int *) malloc(tamVectorPoblacion);
  int posicionCromosoma1 = 0;
  int posicionCromosoma2 = cantGenesEnCromosomaDevice;
  int probabilidad = 80;



  /*2 3 5 1 6 7 4 0
7 0 3 6 5 1 2 4*/
  poblacionActual[0]=1;
  poblacionActual[1]=2;
  poblacionActual[2]=3;
  poblacionActual[3]=4;
  poblacionActual[4]=5;
  poblacionActual[5]=6;
  poblacionActual[6]=7;
  poblacionActual[7]=8;
  poblacionActual[8]=9;

  for(int i =0; i<cantGenesEnCromosomaDevice;i++){
  	  cout<<poblacionActual[i]<<" ";
  }
  cout<<"\n\n";

  mutacionPorMezcla( poblacionActual, posicionCromosoma1, posicionCromosoma2, probabilidad);

  for(int i =0; i<cantGenesEnCromosomaDevice;i++){
	  cout<<poblacionActual[i]<<" ";
  }
  cout<<"\n\n";

  float valor = 2.8;
  valor = fmod(valor, 1);;
  cout<<valor;
  cout<<"\n\n";

  /*for(int i =0; i<cantGenesEnCromosomaDevice;i++){
  	  cout<<nuevaPoblacion[i]<<" ";
    }
  cout<<"\n\n";*/
}

